<!--
 * @Author: 李天惊 uf_lee@163.com
 * @Date: 2022-08-15 16:45:26
 * @LastEditors: 李天惊 uf_lee@163.com
 * @LastEditTime: 2022-11-21 14:56:08
 * @FilePath: \grazlink20\uc_sys\src\components\Lee\Edit\src\LeeEdit2.vue
 * Copyright (c) 2022 by 李天惊 uf_lee@163.com, All Rights Reserved. 
-->
<script lang="tsx">
import { defineComponent, PropType, ref, unref, computed } from 'vue'
import { componentMap } from './componentMap'
import { propTypes } from '@/utils/propTypes'
import { ElForm, ElFormItem, ElRow, ElCol } from 'element-plus'
import {
  // setTextPlaceholder,
  setGridProp,
  // setComponentProps,
  setItemComponentSlots
  // initModel,
  // setFormItemSlots
} from './helper'
import { useRenderSelect } from './components/useRenderSelect'
import { useRenderRadio } from './components/useRenderRadio'
import { useRenderCheckbox } from './components/useRenderCheckbox'

export default defineComponent({
  name: 'LeeEdit2',
  props: {
    // 生成Form的布局结构数组
    schema: {
      type: Array as PropType<any[]>,
      default: () => []
    },
    // 是否需要栅格布局
    isCol: propTypes.bool.def(true),
    // 表单label宽度
    labelWidth: propTypes.oneOfType([String, Number]).def('auto')
  },
  setup(props, { slots }) {
    // 表单数据
    const formModel = ref<any>({})

    const mergeProps = ref<any>({})

    const getProps = computed(() => {
      const propsObj = { ...props }
      Object.assign(propsObj, unref(mergeProps))
      return propsObj
    })

    // 处理回车刷新页面的问题
    const onSubmit = (e: any) => {
      if (e) {
        e.preventDefault()
      }
    }

    // 过滤传入Form组件的属性
    const getFormBindValue = () => {
      // 避免在标签上出现多余的属性
      const delKeys = ['schema', 'isCol', 'autoSetPlaceholder', 'isCustom', 'model']
      const props = { ...unref(getProps) }
      for (const key in props) {
        if (delKeys.indexOf(key) !== -1) {
          delete props[key]
        }
      }
      return props
    }

    // 渲染form
    const renderForm = () => {
      // hidden属性表示隐藏，不做渲染
      const { schema = [], isCol } = unref(props)
      const FormItems = schema.map((item) => {
        return isCol ? (
          <ElCol {...setGridProp(item.colProps)}>{renderFormItem(item)}</ElCol>
        ) : (
          renderFormItem(item)
        )
      })
      const Form = (
        <ElForm onSubmit={onSubmit} {...getFormBindValue()}>
          {isCol ? <ElRow gutter={20}> {FormItems}</ElRow> : FormItems}
        </ElForm>
      )
      return Form
    }

    // 渲染formItem
    const renderFormItem = (item: FormSchema) => {
      const Com = componentMap[item.component as string] as ReturnType<typeof defineComponent>
      const slotsMap: Recordable = {
        ...setItemComponentSlots(slots, item?.componentProps?.slots, item.field)
      }
      if (
        item?.component !== 'SelectV2' &&
        item?.component !== 'Cascader' &&
        item?.componentProps?.options
      ) {
        slotsMap.default = () => renderOptions(item)
      }

      return (
        <ElFormItem label={item.label}>
          <Com vModel={formModel.value[item.field]} {...item.componentProps}>
            {{ ...slotsMap }}
          </Com>
        </ElFormItem>
      )
    }

    // 渲染options
    const renderOptions = (item: FormSchema) => {
      switch (item.component) {
        case 'Select':
          const { renderSelectOptions } = useRenderSelect(slots)
          return renderSelectOptions(item)
        case 'Radio':
        case 'RadioButton':
          const { renderRadioOptions } = useRenderRadio()
          return renderRadioOptions(item)
        case 'Checkbox':
        case 'CheckboxButton':
          const { renderChcekboxOptions } = useRenderCheckbox()
          return renderChcekboxOptions(item)
        default:
          break
      }
    }

    return () => (
      <div>
        {renderForm()}
        <div>{JSON.stringify(formModel.value)}</div>
      </div>
    )
  }
})
</script>
